﻿using System;

using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;

namespace LetsDoIt.Controls
{
	public class DevicesList : OwnerDrawnListBox
	{
		const int FONT_SIZE = 10;
		const int DRAW_OFFSET = 5;

		public Image InternalGpsImage { get; set; }
		public Image BluetoothGpsImage { get; set; }
		public Image SerialGpsImage { get; set; }

		#region Transparent Color
		Color _transparentColor = Color.Fuchsia;
		/// <summary>
		/// Sets or gets transparent color for an Image. The default color is 255, 0, 255.
		/// </summary>
		public Color TransparentColor
		{
			get
			{
				return _transparentColor;
			}
			set
			{
				_transparentColor = value;
				this.Invalidate();
			}
		}

		public object SelectedItem
		{
			get
			{
				if(SelectedIndex>=0)
					return this.Items[SelectedIndex];
				return null;
			}
		}

		#endregion

		private int textHeight = 10;
		public DevicesList()
		{
			// Determine what the item height should be
			// by adding 30% padding after measuring
			// the letter A with the selected font.
			Graphics g = this.CreateGraphics();
			this.ItemHeight = 64;// 
			textHeight = (int)(g.MeasureString("A", this.Font).Height * 1.3);
			g.Dispose();
		}

		public void AddItem(object item)
		{
			Items.Add(item);
			DoResize();
			this.Invalidate();
		}

		public void ClearItems()
		{
			Items.Clear();
			DoResize();
			this.Invalidate();
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			Font font;
			Color fontColor;

			// The base class contains a bitmap, offScreen, for constructing
			// the control and is rendered when all items are populated.
			// This technique prevents flicker.
			Graphics gOffScreen = Graphics.FromImage(this.OffScreen);
			gOffScreen.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);

			int itemTop = 0;
			int textVOffset = (this.ItemHeight - textHeight)/2;
			// Draw the fonts in the list.
			for (int n = this.VScrollBar.Value; n < this.VScrollBar.Value + DrawCount; n++)
			{
				// If the font name contains "dings" it needs to be displayed
				// in the list box with a readable font with the default font.
				//if (((string)this.Items[n]).ToLower().IndexOf("dings") != -1)
				//    font = new Font(this.Font.Name, FONT_SIZE, FontStyle.Regular);
				//else
					//font = new Font((string)this.Items[n], FONT_SIZE, FontStyle.Regular);

				// Draw the selected item to appear highlighted
				if (n == this.SelectedIndex)
				{
					gOffScreen.FillRectangle(new SolidBrush(SystemColors.Highlight),
						1,
						itemTop + 1,
						// If the scroll bar is visible, subtract the scrollbar width
						// otherwise subtract 2 for the width of the rectangle
						this.ClientSize.Width - (this.VScrollBar.Visible ? this.VScrollBar.Width : 2),
						this.ItemHeight);
					fontColor = CalcTextColor(SystemColors.Highlight);
				}
				else
					fontColor = this.ForeColor;

				// Draw the item
				GpsDeviceInfo device = this.Items[n] as GpsDeviceInfo;
				if (device!=null)
				{
					ImageAttributes attr = new ImageAttributes();
					attr.SetColorKey(_transparentColor, _transparentColor);
					//
					switch (device.Type)
					{
						case GpsDeviceInfo.GpsType.Internal:
							if (InternalGpsImage != null)
							{			
								gOffScreen.DrawImage(InternalGpsImage, new Rectangle(DRAW_OFFSET, itemTop, this.ItemHeight, this.ItemHeight), 0, 0, InternalGpsImage.Width, InternalGpsImage.Height,
								                     GraphicsUnit.Pixel, attr);
							}
							break;
						case GpsDeviceInfo.GpsType.Bluetooth:
							if (BluetoothGpsImage != null)
							{
								gOffScreen.DrawImage(BluetoothGpsImage, new Rectangle(DRAW_OFFSET, itemTop, this.ItemHeight, this.ItemHeight), 0, 0, BluetoothGpsImage.Width, BluetoothGpsImage.Height,
													 GraphicsUnit.Pixel, attr);
							}
							break;
						case GpsDeviceInfo.GpsType.Serial:
							if (SerialGpsImage != null)
							{
								gOffScreen.DrawImage(SerialGpsImage, new Rectangle(DRAW_OFFSET, itemTop, this.ItemHeight, this.ItemHeight), 0, 0, SerialGpsImage.Width, SerialGpsImage.Height,
													 GraphicsUnit.Pixel, attr);
							}
							break;
						default:
							break;

					}
					font = new Font(device.Name, FONT_SIZE, FontStyle.Regular);
					gOffScreen.DrawString(device.Name, font, 
						new SolidBrush(fontColor), 
						2 * DRAW_OFFSET + this.ItemHeight,
						itemTop + textVOffset);
				}
				//gOffScreen.DrawString((string)this.Items[n], font, new SolidBrush(fontColor), DRAW_OFFSET, itemTop);
				itemTop += this.ItemHeight;
			}

			// Draw the list box
			e.Graphics.DrawImage(this.OffScreen, 1, 1);

			gOffScreen.Dispose();
		}

		// Draws the external border around the control.
		protected override void OnPaintBackground(PaintEventArgs e)
		{
			e.Graphics.DrawRectangle(new Pen(Color.Black), 0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1);
		}

		// Determine what the text color should be
		// for the selected item drawn as highlighted
		Color CalcTextColor(Color backgroundColor)
		{
			if (backgroundColor.Equals(Color.Empty))
				return Color.Black;

			int sum = backgroundColor.R + backgroundColor.G + backgroundColor.B;

			if (sum > 256)
				return Color.Black;
			else
				return Color.White;
		}

	}
}
